#include "math/vector.h"
#include "math/ray.h"
#include "object/sphere.h"
#include "object/plane.h"
#include "object/cone.h"
#include "object/quadrilateral.h"
#include "object/object.h"
#include "object/triangle.h"
#include "object/disc.h"
#include "object/mesh.h"
#include "object/cylinder.h"
#include "common/scene.h"
#include "common/camera.h"
#include "common/image.h"
#include "common/tga.h"
#include "common/input.h"
#include "common/color.h"
#include "light/punctual_light.h"
#include "light/square_light.h"
#include "light/light.h"
#include "material/light_material.h"
#include "material/material.h"
#include "material/object_material.h"
#include "material/color_material.h"
#include "photonmapping/photontracer.h"
#include "photonmapping/kd_tree.h"
#include "raytracing/raytracer.h"
#include "pathtracing/pathtracer.h"
#include "bdpt/tracer.h"

#define ALTURA 500
#define LARGURA 500

#include <boost/config.hpp>

#include <iomanip>
#include <iostream>
#include <fstream>
#include <string>

#include <boost/serialization/export.hpp>

#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

using namespace Sirat;
using namespace Sirat::Common;
using namespace Sirat::Light;
using namespace Sirat::Material;
using namespace Sirat::Math;
using namespace Sirat::Object;
using namespace Sirat::Photon_Mapping;
using namespace Sirat::Ray_Tracing;
using namespace Sirat::Path_Tracing;

Light_Material* l = new Light_Material(Color(1.0,1.0,1.0),1);

Object_Material* m0 = new Color_Material(Color(0.0,0.0,0.0),Color(0.0,1.0,0.0),Color(0.0,0.0,0.0),Color(0.0,0.0,0.0),50);
Object_Material* m1 = new Color_Material(Color(0.0,0.0,0.0),Color(1.0,1.0,1.0),Color(0.0,0.0,0.0),Color(1.0,1.0,1.0),50);
Sirat::Light::Light* luz1 = new Punctual_Light(l,Vector(4.0,0.0,0.0));
Sirat::Light::Light* luz2 = new Punctual_Light(l,Vector(0.0,0.0,5.904));

#include <fstream>
#include <vector>

using namespace std;
using namespace boost::archive;

int main(int argc, char** argv) {
	Tga* file = new Tga(LARGURA, ALTURA);
	/*Scene* scene = new Scene(Color(0.0,0.0,0.0),1.0);
	Camera* camera = new Camera(Vector(0.0,5.056,0.964), Vector(0.0,4.356,0.964), Vector(0.0,0.0,1.0), LARGURA,ALTURA,Planar);
	//Camera* camera = new Camera(Vector(0.0,0.0,5.0), Vector(0.0,0.0,3.0), Vector(0.0,1.0,0.0), LARGURA,ALTURA,Planar);
	scene->add_object(new Mesh(m0, "examples/gaita.obj", 3));
	scene->add_object(new Mesh(m1, "examples/plane1.obj", 3));
	//scene->add_object(new Sphere(m0, Vector(0,0,0), 1));
	//scene->add_object(new Plane(m1, Vector(0,-1,0), Vector(0,1,0)));
	scene->add_light(luz2);
	//scene->set_optimization(true, 20);

	std::ofstream ofs("cena.sirat");
	text_oarchive oa(ofs);
	oa & scene & camera;
	return 0;*/

	Scene *scene;
	Camera *camera;

	std::ifstream ifs("cena.sirat");
	text_iarchive ia(ifs);
	ia & scene & camera;

	Raytracer* r = new Raytracer(scene,camera,0);
	Photontracer* p = new Photontracer(scene,3,30000);
	Path_Tracer* path = new Path_Tracer(scene, camera, 1000, 6);
	BDPT::Tracer* bdpt = new BDPT::Tracer(scene, camera, 1000, 3, 3);

	/*bdpt->set_parallel(true);
	bdpt->set_threads(4);
	bdpt->set_output(file);
	bdpt->render();
	file->save_file("bdpt.tga");

	path->set_parallel(true);
	path->set_threads(4);
	
	path->set_output(file);
	path->render();
	file->save_file("path.tga");*/

	r->set_parallel(true);
	r->set_threads(4);

	r->set_output(file);
	r->render();
	file->save_file("ray.tga");
	
	/*p->trace();
	r->set_photon_map(p->get_photon_map(), 500);
	r->render();
	file->save_file("photon.tga");*/

	return 0;
}
